﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Reflection;
using System.Text;

namespace APICommond
{
    public static class DataTableToList
    {
        public static IEnumerable<T> ToEntitys<T>(this DataTable dt) where T : new()
        {
            Type type = typeof(T);
            PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
            FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
            List<T> list = new List<T>();
            foreach (DataRow dr in dt.Rows)
            {
                T entity = (default(T) == null) ? Activator.CreateInstance<T>() : default(T);
                PropertyInfo[] array = properties;
                for (int i = 0; i < array.Length; i++)
                {
                    PropertyInfo property = array[i];
                    if (dt.Columns.Contains(property.Name))
                    {
                        Type valueType = property.PropertyType;
                        property.SetValue(entity, Convert.ChangeType(dr[property.Name], valueType), null);
                    }
                }
                FieldInfo[] array2 = fields;
                for (int j = 0; j < array2.Length; j++)
                {
                    FieldInfo field = array2[j];
                    if (dt.Columns.Contains(field.Name))
                    {
                        Type valueType2 = field.FieldType;
                        field.SetValue(entity, Convert.ChangeType(dr[field.Name], valueType2));
                    }
                }
                list.Add(entity);
            }
            return list;
        }

        public static T GetEntity<T>(DataTable table) where T : new()
        {
            T entity = new T();
            foreach (DataRow row in table.Rows)
            {
                foreach (var item in entity.GetType().GetProperties())
                {
                    if (row.Table.Columns.Contains(item.Name))
                    {
                        if (DBNull.Value != row[item.Name])
                        {
                            item.SetValue(entity, ChanageType(row[item.Name], item.PropertyType), null);
                        }
                    }
                }
            }
            return entity;
        }

        public static IList<T> GetEntities<T>(DataTable table) where T : new()
        {
            IList<T> entities = new List<T>();
            foreach (DataRow row in table.Rows)
            {
                T entity = new T();
                foreach (var item in entity.GetType().GetProperties())
                {
                    item.SetValue(entity, ChanageType(row[item.Name], item.PropertyType), null);
                }
                entities.Add(entity);
            }
            return entities;
        }

        //转换可空类型 如：DateTime? 
        private static object ChanageType(object value, Type convertsionType)
        {
            //判断convertsionType类型是否为泛型，因为nullable是泛型类,
            if (convertsionType.IsGenericType &&
                //判断convertsionType是否为nullable泛型类
                convertsionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                if (value == null || value.ToString().Length == 0)
                {
                    return null;
                }

                //如果convertsionType为nullable类，声明一个NullableConverter类，该类提供从Nullable类到基础基元类型的转换
                NullableConverter nullableConverter = new NullableConverter(convertsionType);
                //将convertsionType转换为nullable对的基础基元类型
                convertsionType = nullableConverter.UnderlyingType;
            }
            return Convert.ChangeType(value, convertsionType);
        }
    }
}
